#ifndef __SERIAL_PROTOCOL_H
#define __SERIAL_PROTOCOL_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>

typedef void (*SerialProtocol_CallbackTypedef)(uint8_t address, uint8_t length, uint8_t *data);

typedef enum {
    STATE_IDLE,   // 启动状态机，接收启动字节0x80
    STATE_ADDR,   // 接收写入地址
    STATE_LENGTH, // 接收数据长度
    STATE_DATA,   // 接收数据
    STATE_STOP,   // 接受终止字节0xff，然后可以执行回调函数
    STATE_WAIT_CB // 等待回调函数执行
} SerialProtocol_State_EnumTypedef;

typedef struct {
    // 数据缓冲区
    uint8_t *buffer;
    // 数据缓冲区指针
    uint8_t bufferIndex;
    // 数据包地址
    uint8_t packetAddress;
    // 数据包长度
    uint8_t packetLength;
    // 标志位，指示回调函数是否已经设置
    bool callbackRegistered;
    // 回调函数
    SerialProtocol_CallbackTypedef callbackFunc;
    // 状态机
    SerialProtocol_State_EnumTypedef state;
    // 是否可执行回调函数
    bool callbackReady;
} SerialProtocol_HandleTypedef;


/*
    @brief 向缓冲区输入一个字符
    @param handle 协议句柄
    @param data 数据（单个字节）
*/
void SerialProtocol_PutByte(SerialProtocol_HandleTypedef *handle, uint8_t data);

/*
    @brief 初始化协议句柄
    @param handle 协议句柄
    @param bufferSize 缓冲区大小
*/
void SerialProtocol_InitHandle(SerialProtocol_HandleTypedef *handle, uint8_t bufferSize);

/*
    @brief 对协议句柄注册回调函数
    @param handle 协议句柄
    @param callback 回调函数的函数指针
*/
void SerialProtocol_RegisterCallback(SerialProtocol_HandleTypedef *handle, SerialProtocol_CallbackTypedef callback);

/*
    @brief 如果数据已经就绪，执行协议的回调函数
    @param handle 协议句柄
    @retval 若成功执行则返回0，否则返回-1
*/
int SerialProtocol_RequestCallback(SerialProtocol_HandleTypedef *handle);

/*
    @brief 重置状态机
    @param handle 协议句柄
*/
void SerialProtocol_ResetStateMachine(SerialProtocol_HandleTypedef *handle);

/*
    @brief 回复数据
    @param handle 协议句柄
    @param data 传回数据
    @param length 传回数据长度
*/
void SerialProtocol_Reply(SerialProtocol_HandleTypedef *handle, uint8_t *data, uint8_t length);

#ifdef __cplusplus
};
#endif

#endif
